const ncname = `[a-zA-Z_][\\-\\.0-9_a-zA-Z]*`; // 标签名称
const qnameCapture = `((?:${ncname}\\:)?${ncname})`; // <div :calss>
const startTagOpen = new RegExp(`^<${qnameCapture}`); // 开始标签
const endTag = new RegExp(`^<\\/${qnameCapture}[^>]*>`); // 结束标签
const attribute = /^\s*([^\s"'<>\/=]+)(?:\s*(=)\s*(?:"([^"]*)"+|'([^']*)'+|([^\s"'=<>`]+)))?/;
const startTagClose = /^\s*(\/?)>/; // 开始标签的 >
const defaultTagRE = /\{\{((?:.|\r?\n)+?)\}\}/g; //{{}}



export function parseHTML(html) {
    // 创建ast节点
    function createAstEl(tag, attrs) {
        return {
            tag, attrs, children: [], type: 1, parent: null
        }
    }

    let root
    let currentParent
    let stack = []

    function start(tag, attrs) {
        let el = createAstEl(tag, attrs)
        if (!root) {
            root = el
        }
        currentParent = el
        stack.push(el)
    }

    function charts(text) {
        // 处理空格
        text = text.replace(/ /g, '')
        if (text) {
            // 这里的currentParent是start方法里面赋值的，代表当前解析到的DOM节点
            currentParent.children.push({
                type: 3, text
            })
        }
    }

    function end() {
        let el = stack.pop()
        currentParent = stack[stack.length - 1]
        if (currentParent) {
            el.parent = currentParent.tag
            currentParent.children.push(el)
        }
    }
    while (html) {
        // 判断<
        let textEnd = html.indexOf("<");
        if (textEnd === 0) {
            const startTagMatch = parseStartTag();
            // 开始标签
            if (startTagMatch) {
                start(startTagMatch.tagName, startTagMatch.attrs);
                continue;
            }
            // 结束标签
            let endTagMatch = html.match(endTag);
            if (endTagMatch) {
                advance(endTagMatch[0].length);
                end();
                continue;
            }
        }
        // 处理文本
        if (textEnd > 0) {
            let text = html.substring(0, textEnd);
            if (text) {
                advance(text.length);
                charts(text);
            }
        }
    }

    function parseStartTag() {
        const start = html.match(startTagOpen);
        if (start) {
            let match = {
                tagName: start[1],
                attrs: [],
            };
            advance(start[0].length);
            let attr;
            let end;
            // 没有闭合标签 && 存在属性
            while (
                !(end = html.match(startTagClose)) &&
                (attr = html.match(attribute))
            ) {
                match.attrs.push({
                    name: attr[1],
                    value: attr[3] || attr[4] || attr[5],
                });
                advance(attr[0].length);
            }
            if (end) {
                advance(end[0].length);
                return match;
            }
        }
    }

    function advance(n) {
        html = html.substring(n);
    }

    return root
}